﻿using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Forms;

namespace Haidou.Wpf.Util
{
	public enum MouseEventFlags : uint
	{
		Move = 0x0001,
		LeftDown = 0x0002,
		LeftUp = 0x0004,
		RightDown = 0x0008,
		RightUp = 0x0010,
		MiddleDown = 0x0020,
		MiddleUp = 0x0040,
		Absolute = 0x8000
	}

	public static class Win32
	{


		public const uint WM_SYSCOMMAND = 0x0112, WM_MOUSEACTIVATE = 0x0021, WM_NCLBUTTONDOWN = 0x00A1, WM_LBUTTONDOWN = 0x0201;

		public const int SC_MOVE = 61456;

		public const int WM_NCHITTEST = 0x84;          // 用于拖动表单的变量
		public const int HTCLIENT = 0x1;
		public const int HTCAPTION = 0x2;
		public const int WM_NCACTIVATE = 0x0086;
		public const int HTNOWHERE = 0;
		public const int HTGROWBOX = 4;
		public const int HTSIZE = HTGROWBOX;
		public const int HTMINBUTTON = 8;
		public const int HTMAXBUTTON = 9;
		public const int HTLEFT = 10;
		public const int HTRIGHT = 11;
		public const int HTTOP = 12;
		public const int HTTOPLEFT = 13;
		public const int HTTOPRIGHT = 14;
		public const int HTBOTTOM = 15;
		public const int HTBOTTOMLEFT = 16;
		public const int HTBOTTOMRIGHT = 17;
		public const int HTREDUCE = HTMINBUTTON;
		public const int HTZOOM = HTMAXBUTTON;
		internal const int WM_LBUTTONUP = 0x0202;
		public const int WM_MOUSEMOVE = 0x0200;
		internal const int WM_MOUSEHOVER = 0x02A0;
		public const int WM_CEF_RESIZE_CLIENT = 0x0400 + 1001;

		public static int LoWord(int dwValue)
		{
			return dwValue & 0xffff;
		}

		public static int HiWord(int dwValue)
		{
			return (dwValue >> 16) & 0xffff;
		}

		[DllImport("user32.dll")]
		public static extern void LockWorkStation();


		[DllImport("user32.dll")]
		public static extern bool ReleaseCapture();

		[DllImport("user32.dll")]
		public static extern bool SendMessage(IntPtr hwnd, uint wMsg, int wParam, int lParam);

		[DllImport("User32.DLL")]
		public static extern int PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

		[DllImport("user32.dll", SetLastError = true)]
		public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

		[DllImport("user32.dll")]
		public static extern IntPtr FindWindow(string className, string windowTitle);


		[DllImport("user32.dll", EntryPoint = "GetDesktopWindow", CharSet = CharSet.Auto, SetLastError = true)]
		public static extern IntPtr GetDesktopWindow();

		[DllImport("user32.dll", SetLastError = true)]
		public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);


		[DllImport("user32.dll", SetLastError = true)]
		public static extern int GetClassName(
IntPtr hWnd,//句柄 
  StringBuilder lpString, //类名 
  int nMaxCount //最大值 
  );


		[DllImport("User32.dll", CharSet = CharSet.Auto)]
		public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int nMaxCount);

		[DllImport("User32.dll")]
		public static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
		[DllImport("User32.dll")]
		public static extern bool SetForegroundWindow(System.IntPtr hWnd);

		[DllImport("user32.dll")]
		public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect);

		[DllImport("user32.dll")]
		public static extern IntPtr GetActiveWindow();

		[DllImport(@"sbcble.dll", EntryPoint = "Init_sbc", CallingConvention = CallingConvention.Cdecl)]
		public static extern void Init_sbc();

		[DllImport(@"sbcble.dll", EntryPoint = "Sbc_decoder", CallingConvention = CallingConvention.Cdecl)]
		public static extern void Sbc_decoder(byte[] input, ref byte str_out);



		/// <summary>
		/// 移动窗口
		/// </summary>
		/// <param name="window"></param>
		public static void MoveWindow(Form window)
		{
			if (window.WindowState != FormWindowState.Maximized)
			{
				Win32.ReleaseCapture();
				Win32.SendMessage(window.Handle, Win32.WM_SYSCOMMAND, Win32.SC_MOVE + Win32.HTCAPTION, 0);
			}
		}

		public const int GWL_EXSTYLE = -20;
		public const int WS_EX_TRANSPARENT = 0x00000020;
		public const int WS_EX_LAYERED = 0x00080000;

		[StructLayout(LayoutKind.Sequential)]
		public struct Size
		{
			public Int32 cx;
			public Int32 cy;

			public Size(Int32 x, Int32 y)
			{
				cx = x;
				cy = y;
			}
		}

		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		public struct BLENDFUNCTION
		{
			public byte BlendOp;
			public byte BlendFlags;
			public byte SourceConstantAlpha;
			public byte AlphaFormat;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct Point
		{
			public Int32 x;
			public Int32 y;

			public Point(Int32 x, Int32 y)
			{
				this.x = x;
				this.y = y;
			}
		}

		public const byte AC_SRC_OVER = 0;
		public const Int32 ULW_ALPHA = 2;
		public const byte AC_SRC_ALPHA = 1;

		/// <summary>
		/// 从左到右显示
		/// </summary>
		public const Int32 AW_HOR_POSITIVE = 0x00000001;
		/// <summary>
		/// 从右到左显示
		/// </summary>
		public const Int32 AW_HOR_NEGATIVE = 0x00000002;
		/// <summary>
		/// 从上到下显示
		/// </summary>
		public const Int32 AW_VER_POSITIVE = 0x00000004;
		/// <summary>
		/// 从下到上显示
		/// </summary>
		public const Int32 AW_VER_NEGATIVE = 0x00000008;
		/// <summary>
		/// 若使用了AW_HIDE标志，则使窗口向内重叠，即收缩窗口；否则使窗口向外扩展，即展开窗口
		/// </summary>
		public const Int32 AW_CENTER = 0x00000010;
		/// <summary>
		/// 隐藏窗口，缺省则显示窗口
		/// </summary>
		public const Int32 AW_HIDE = 0x00010000;
		/// <summary>
		/// 激活窗口。在使用了AW_HIDE标志后不能使用这个标志
		/// </summary>
		public const Int32 AW_ACTIVATE = 0x00020000;
		/// <summary>
		/// 使用滑动类型。缺省则为滚动动画类型。当使用AW_CENTER标志时，这个标志就被忽略
		/// </summary>
		public const Int32 AW_SLIDE = 0x00040000;
		/// <summary>
		/// 透明度从高到低
		/// </summary>
		public const Int32 AW_BLEND = 0x00080000;


		public static int MakeLParam(int LoWord, int HiWord)
		{
			return (HiWord << 16) | (LoWord & 0xffff);
		}

		/// <summary>
		/// 执行动画
		/// </summary>
		/// <param name="whnd">控件句柄</param>
		/// <param name="dwtime">动画时间</param>
		/// <param name="dwflag">动画组合名称</param>
		/// <returns>bool值，动画是否成功</returns>
		[DllImport("user32")]
		public static extern bool AnimateWindow(IntPtr whnd, int dwtime, int dwflag);

		/// <summary>
		/// <para>该函数将指定的消息发送到一个或多个窗口。</para>
		/// <para>此函数为指定的窗口调用窗口程序直到窗口程序处理完消息再返回。</para>
		/// <para>而函数PostMessage不同，将一个消息寄送到一个线程的消息队列后立即返回。</para>
		/// return 返回值 : 指定消息处理的结果，依赖于所发送的消息。
		/// </summary>
		/// <param name="hWnd">要接收消息的那个窗口的句柄</param>
		/// <param name="Msg">消息的标识符</param>
		/// <param name="wParam">具体取决于消息</param>
		/// <param name="lParam">具体取决于消息</param>
		[DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessageA")]
		public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);


		[DllImport("user32.dll", EntryPoint = "keybd_event")]

		public static extern void keybd_event(

			byte bVk,    //虚拟键值

			byte bScan,// 一般为0

			int dwFlags,  //这里是整数类型  0 为按下，2为释放

			int dwExtraInfo  //这里是整数类型 一般情况下设成为 0

		);

		[DllImport("user32")]
		public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

		[DllImport("gdi32.dll")]
		public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);

		[DllImport("user32.dll")]
		public static extern int SetWindowRgn(IntPtr hwnd, int hRgn, Boolean bRedraw);

		[DllImport("user32", EntryPoint = "GetWindowLong")]
		public static extern int GetWindowLong(
			IntPtr hwnd, int nIndex);

		[DllImport("user32.dll")]
		public static extern int SetWindowLong(
			IntPtr hwnd, int nIndex, int dwNewLong);

		[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern IntPtr CreateCompatibleDC(IntPtr hDC);

		[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern IntPtr GetDC(IntPtr hWnd);

		[DllImport("gdi32.dll", ExactSpelling = true)]
		public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObj);

		[DllImport("user32.dll", ExactSpelling = true)]
		public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

		[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern int DeleteDC(IntPtr hDC);

		[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern int DeleteObject(IntPtr hObj);

		[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern int UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pptSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags);

		[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
		public static extern IntPtr ExtCreateRegion(IntPtr lpXform, uint nCount, IntPtr rgnData);





		public const int WM_GETMINMAXINFO = 0x0024;

		// 检索离窗口最近的显示监视器的句柄
		public const int MONITOR_DEFAULTTONEAREST = 2;

		// 检索到显示监视器的句柄
		[DllImport("user32.dll")]
		public static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags);

		// RECT结构，MONITORINFOEX使用的矩形
		[StructLayout(LayoutKind.Sequential)]
		public struct RECT
		{
			public int Left;
			public int Top;
			public int Right;
			public int Bottom;
		}

		// MINMAXINFO结构，窗口的最大尺寸和位置信息
		[StructLayout(LayoutKind.Sequential)]
		public struct MINMAXINFO
		{
			public Point ptReserved;
			public Point ptMaxSize; // 窗口的最大化尺寸
			public Point ptMaxPosition; // 最大化窗口的位置
			public Point ptMinTrackSize;
			public Point ptMaxTrackSize;
		}

		// MONITORINFOEX结构，GetMonitorInfo函数使用的监控信息
		[StructLayout(LayoutKind.Sequential)]
		public class MONITORINFOEX
		{
			public int cbSize;
			public RECT rcMonitor; // 显示监视器矩形
			public RECT rcWork; // 工作区矩形
			public int dwFlags;
			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
			public char[] szDevice;
		}

		// 获取指定监视器的工作区域
		[DllImport("user32.dll")]
		public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX monitorInfo);


		/// <summary>
		/// 指示光标作用点的位置。
		/// </summary>
		public enum HitTest : int
		{
			/// <summary>
			/// 在屏幕背景上或窗口之间的分界线上(与HTNOWHERE相同，只是DefWindowProc函数会发出系统嘟嘟声来指示错误)。
			/// </summary>
			HTERROR = -2,

			/// <summary>
			/// In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).
			/// </summary>
			HTTRANSPARENT = -1,

			/// <summary>
			/// On the screen background or on a dividing line between windows.
			/// </summary>
			HTNOWHERE = 0,

			/// <summary>
			/// In a client area.
			/// </summary>
			HTCLIENT = 1,

			/// <summary>
			/// In a title bar.
			/// </summary>
			HTCAPTION = 2,

			/// <summary>
			/// In a window menu or in a Close button in a child window.
			/// </summary>
			HTSYSMENU = 3,

			/// <summary>
			/// In a size box (same as HTSIZE).
			/// </summary>
			HTGROWBOX = 4,

			/// <summary>
			/// In a size box (same as HTGROWBOX).
			/// </summary>
			HTSIZE = 4,

			/// <summary>
			/// In a menu.
			/// </summary>
			HTMENU = 5,

			/// <summary>
			/// In a horizontal scroll bar.
			/// </summary>
			HTHSCROLL = 6,

			/// <summary>
			/// In the vertical scroll bar.
			/// </summary>
			HTVSCROLL = 7,

			/// <summary>
			/// In a Minimize button.
			/// </summary>
			HTMINBUTTON = 8,

			/// <summary>
			/// In a Minimize button.
			/// </summary>
			HTREDUCE = 8,

			/// <summary>
			/// In a Maximize button.
			/// </summary>
			HTMAXBUTTON = 9,

			/// <summary>
			/// In a Maximize button.
			/// </summary>
			HTZOOM = 9,

			/// <summary>
			/// In the left border of a resizable window (the user can click the mouse to resize the window horizontally).
			/// </summary>
			HTLEFT = 10,

			/// <summary>
			/// In the right border of a resizable window (the user can click the mouse to resize the window horizontally).
			/// </summary>
			HTRIGHT = 11,

			/// <summary>
			/// In the upper-horizontal border of a window.
			/// </summary>
			HTTOP = 12,

			/// <summary>
			/// In the upper-left corner of a window border.
			/// </summary>
			HTTOPLEFT = 13,

			/// <summary>
			/// In the upper-right corner of a window border.
			/// </summary>
			HTTOPRIGHT = 14,

			/// <summary>
			/// In the lower-horizontal border of a resizable window (the user can click the mouse to resize the window vertically).
			/// </summary>
			HTBOTTOM = 15,

			/// <summary>
			/// In the lower-left corner of a border of a resizable window (the user can click the mouse to resize the window diagonally).
			/// </summary>
			HTBOTTOMLEFT = 16,

			/// <summary>
			/// In the lower-right corner of a border of a resizable window (the user can click the mouse to resize the window diagonally).
			/// </summary>
			HTBOTTOMRIGHT = 17,

			/// <summary>
			/// In the border of a window that does not have a sizing border.
			/// </summary>
			HTBORDER = 18,

			/// <summary>
			/// In a Close button.
			/// </summary>
			HTCLOSE = 20,

			/// <summary>
			/// In a Help button.
			/// </summary>
			HTHELP = 21,
		};

		/// <summary>
		/// 向全局原子表添加一个字符串，并返回这个字符串的唯一标识符,成功则返回值为新创建的原子ID,失败返回0
		/// </summary>
		/// <param name="lpString"></param>
		/// <returns></returns>
		[DllImport("kernel32", SetLastError = true)]
		public static extern short GlobalAddAtom(string lpString);

		[DllImport("kernel32", SetLastError = true)]
		public static extern short GlobalDeleteAtom(short nAtom);

		/// <summary>
		/// 如果函数执行成功，返回值不为0。
		/// 如果函数执行失败，返回值为0。要得到扩展错误信息，调用GetLastError。.NET方法:Marshal.GetLastWin32Error()
		/// </summary>
		/// <param name="hWnd">要定义热键的窗口的句柄</param>
		/// <param name="id">定义热键ID（不能与其它ID重复）  </param>
		/// <param name="fsModifiers">标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效</param>
		/// <param name="vk">定义热键的内容,WinForm中可以使用Keys枚举转换，
		/// WPF中Key枚举是不正确的,应该使用System.Windows.Forms.Keys枚举，或者自定义正确的枚举或int常量</param>
		/// <returns></returns>
		[DllImport("user32.dll", SetLastError = true)]
		public static extern bool RegisterHotKey(
			IntPtr hWnd,
			int id,
			KeyModifiers fsModifiers,
			int vk
			);

		/// <summary>
		/// 取消注册热键
		/// </summary>
		/// <param name="hWnd">要取消热键的窗口的句柄</param>
		/// <param name="id">要取消热键的ID</param>
		/// <returns></returns>
		[DllImport("user32.dll", SetLastError = true)]
		public static extern bool UnregisterHotKey(
			IntPtr hWnd,
			int id
			);

		/// <summary>
		/// 定义了辅助键的名称（将数字转变为字符以便于记忆，也可去除此枚举而直接使用数值）
		/// </summary>
		[Flags()]
		public enum KeyModifiers
		{
			None = 0,
			Alt = 1,
			Ctrl = 2,
			Shift = 3,
			WindowsKey = 4
		}

		/// <summary>
		/// 热键的对应的消息ID
		/// </summary>
		public const int WmHotkey = 0x312;
	}

	//public struct Rect
	//{
	//    public int Left;
	//    public int Top;
	//    public int Right;
	//    public int Bottom;
	//}


	public enum GetWindowCmd : uint
	{
		/// <summary>
		/// 返回的句柄标识了在Z序最高端的相同类型的窗口。
		/// 如果指定窗口是最高端窗口，则该句柄标识了在Z序最高端的最高端窗口；
		/// 如果指定窗口是顶层窗口，则该句柄标识了在z序最高端的顶层窗口：
		/// 如果指定窗口是子窗口，则句柄标识了在Z序最高端的同属窗口。
		/// </summary>
		GW_HWNDFIRST = 0,
		/// <summary>
		/// 返回的句柄标识了在z序最低端的相同类型的窗口。
		/// 如果指定窗口是最高端窗口，则该柄标识了在z序最低端的最高端窗口：
		/// 如果指定窗口是顶层窗口，则该句柄标识了在z序最低端的顶层窗口；
		/// 如果指定窗口是子窗口，则句柄标识了在Z序最低端的同属窗口。
		/// </summary>
		GW_HWNDLAST = 1,
		/// <summary>
		/// 返回的句柄标识了在Z序中指定窗口下的相同类型的窗口。
		/// 如果指定窗口是最高端窗口，则该句柄标识了在指定窗口下的最高端窗口：
		/// 如果指定窗口是顶层窗口，则该句柄标识了在指定窗口下的顶层窗口；
		/// 如果指定窗口是子窗口，则句柄标识了在指定窗口下的同属窗口。
		/// </summary>
		GW_HWNDNEXT = 2,
		/// <summary>
		/// 返回的句柄标识了在Z序中指定窗口上的相同类型的窗口。
		/// 如果指定窗口是最高端窗口，则该句柄标识了在指定窗口上的最高端窗口；
		/// 如果指定窗口是顶层窗口，则该句柄标识了在指定窗口上的顶层窗口；
		/// 如果指定窗口是子窗口，则句柄标识了在指定窗口上的同属窗口。
		/// </summary>
		GW_HWNDPREV = 3,
		/// <summary>
		/// 返回的句柄标识了指定窗口的所有者窗口（如果存在）。
		/// GW_OWNER与GW_CHILD不是相对的参数，没有父窗口的含义，如果想得到父窗口请使用GetParent()。
		/// 例如：例如有时对话框的控件的GW_OWNER，是不存在的。
		/// </summary>
		GW_OWNER = 4,
		/// <summary>
		/// 如果指定窗口是父窗口，则获得的是在Tab序顶端的子窗口的句柄，否则为NULL。
		/// 函数仅检查指定父窗口的子窗口，不检查继承窗口。
		/// </summary>
		GW_CHILD = 5,
		/// <summary>
		/// （WindowsNT 5.0）返回的句柄标识了属于指定窗口的处于使能状态弹出式窗口（检索使用第一个由GW_HWNDNEXT 查找到的满足前述条件的窗口）；
		/// 如果无使能窗口，则获得的句柄与指定窗口相同。
		/// </summary>
		GW_ENABLEDPOPUP = 6
	}
}
